﻿using System;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Mt.Site.Application.Members.BackEnd.Dto;
using Abp.Domain.Repositories;
using Mt.Site.Core.Members;
using Abp.Linq.Extensions;
using Abp.Linq;
using System.Linq;
using Abp.AutoMapper;
using System.Collections.Generic;
using Abp.Application.Features;
using Abp.Authorization;
using Mt.Site.Core.Members.Features;
using Mt.Site.Core.Members.Permissions;
using Mt.Site.Application.Dto;
using Mt.Site.Core.Navigations;
using Microsoft.EntityFrameworkCore;

namespace Mt.Site.Application.Members.BackEnd
{
    [RequiresFeature(MemberFeatures.MemberFeature)]
    public class MemberAppService : MtSiteAppServiceBase, IMemberAppService
    {
        public readonly IRepository<Member, Guid> _memberRepository;

        public readonly IRepository<MemberInfo, Guid> _memberInfoRepository;

        public readonly IMemberManager _memberManager;

        private readonly IExportMemberHelper _exportMemberHelper;

        private readonly IMenuStore _menuStore;

        public MemberAppService(
                                IRepository<Member, Guid> MemberRepository,
                                IRepository<MemberInfo, Guid> MemberInfoRepository,
                                IMemberManager memberManager,
                                IMenuStore menustore,
                                IExportMemberHelper exportMemberHelper
                               )
        {
            _memberRepository = MemberRepository;
            _memberInfoRepository = MemberInfoRepository;
            _memberManager = memberManager;
            _menuStore = menustore;
            _exportMemberHelper = exportMemberHelper;
        }


        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Query)]
        public async Task<PagedResultDto<PageMembersOut>> GetPagedMembers(PageMemberInput input)
        {
            DateTime? startTime = input.StartTime;
            DateTime? endTime = input.EndTime;

            if (endTime == null || startTime == null)
            {
                startTime = null;
                endTime = null;
            }

            if (startTime > endTime)
            {
                startTime = null;
                endTime = null;
            }

            var query = from member in _memberRepository.GetAll()
                                                        .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), item => item.LoginName.Contains(input.Filter) || item.Email.Contains(input.Filter))
                                                        .WhereIf(input.IsReceive != null,item=>item.IsReceive == input.IsReceive)
                                                        .WhereIf(input.Enabled != null,item=>item.IsActive == input.Enabled)
                                                        .WhereIf(input.IsTrainingAllowed != null,item=>item.IsTrainingAllowed == input.IsTrainingAllowed)
                                                        .WhereIf(!string.IsNullOrWhiteSpace(input.RegisterFrom), item => item.RegisterForm.Contains(input.RegisterFrom))
                                                        .WhereIf(input.StartTime != null && input.EndTime != null, t => t.CreationTime > startTime && t.CreationTime < endTime)
                        join info in _memberInfoRepository.GetAll()
                                                          .WhereIf(!string.IsNullOrWhiteSpace(input.Country), item => item.Country.Contains(input.Country))
                        on member.Id equals info.MemberID
                        select new
                        {
                            Member = member,
                            Country = info.Country
                        };

            query = query.OrderByDescending(item => item.Member.CreationTime);
            var count = query.Count();
            var list = await query.PageBy(input).ToListAsync();

            var memberList = new List<PageMembersOut>();
            foreach (var item in list)
            {
                var member = new PageMembersOut();
                member.CreationTime = item.Member.CreationTime;
                member.Email = item.Member.Email;
                member.Id = item.Member.Id;
                member.IsActive = item.Member.IsActive;
                member.IsReceive = item.Member.IsReceive;
                member.LoginName = item.Member.LoginName;
                member.RegisterForm = item.Member.RegisterForm;
                member.Country = item.Country;
                member.IsTrainingAllowed = item.Member.IsTrainingAllowed;
                memberList.Add(member);
            }

            return new PagedResultDto<PageMembersOut>(count, memberList);
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Query)]
        public async Task<MemberInfoOut> GetMemberInfoAsync(EntityDto<Guid> input)
        {
            var query = _memberInfoRepository.GetAll().Where(item => item.MemberID == input.Id);
            var entity = await query.FirstOrDefaultAsync();
            var result = new MemberInfoOut();
            if (entity != null)
            {
                result = ObjectMapper.Map<MemberInfoOut>(entity);
            }
            return result;
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Query)]
        public async Task<MemberOut> GetMemberAsync(EntityDto<Guid> input)
        {
            var entity = await _memberRepository.GetAsync(input.Id);
            return ObjectMapper.Map<MemberOut>(entity);
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Delete)]
        public async Task DeleteMemberAsync(DeleteMemberInput input)
        {
            var list = await _memberRepository.GetAllListAsync(item => input.DeleteList.Contains(item.Id));
            foreach (var item in list)
            {
                await _memberManager.DeleteMember(item.Id);
            }
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Update)]
        public async Task ResetPassword(ResetMemberPasswordInput input)
        {
            var list = await _memberRepository.GetAllListAsync(item => input.Ids.Contains(item.Id));

            foreach (var item in list)
            {
                await _memberManager.ResetPassword(item.Id);
            }
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Update)]
        public async Task UpdateMemberAsync(MemberInput input)
        {
            var entity = await _memberRepository.GetAsync(input.Id);
            entity.LoginName = input.LoginName;
            entity.Email = input.Email;
            entity.IsActive = input.IsActive;
            entity.IsReceive = input.IsReceive;
            entity.IsTrainingAllowed = input.IsTrainingAllowed;
            await _memberManager.UpdateMemberAsync(entity);
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Update)]
        public async Task UpdateMemberInfoAsync(MemberInfoInput input)
        {
            var entity = await _memberInfoRepository.FirstOrDefaultAsync(item => item.MemberID == input.Id);
            if (entity != null)
            {
                entity.Address = input.Address;
                entity.Address1 = input.Address1;
                entity.City = input.City;
                entity.Company = input.Company;
                entity.Country = input.Country;
                entity.Fax = input.Fax;
                entity.FirstName = input.FirstName;
                entity.JobTitle = input.JobTitle;
                entity.LastName = input.LastName;
                entity.Phone = input.Phone;
                entity.Province = input.Province;
                entity.Remark = input.Remark;
                entity.Sex = input.Sex;
                entity.Tel = input.Tel;
                entity.WebPage = input.WebPage;
                entity.ZipCode = input.ZipCode;
                entity.FullName = input.FullName;
                await _memberManager.AddOrUpdateMemberInfoAsync(entity);
            }
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_Update)]
        public async Task UpdateMemberState(MemberStateInput input)
        {
            var list = await _memberRepository.GetAllListAsync(item => input.Ids.Contains(item.Id));
            foreach (var item in list)
            {
                item.IsActive = input.Enabled;
                await _memberManager.UpdateMemberAsync(item);
            }
        }

        [AbpAuthorize(MemberPermissions.Pages_Manage_Member_ExportOut)]
        public async Task<FileDto> DataExport(ExportList input)
        {
            DateTime? startTime = input.StartTime;
            DateTime? endTime = input.EndTime;

            if (endTime == null || startTime == null)
            {
                startTime = null;
                endTime = null;
            }

            if (startTime > endTime)
            {
                startTime = null;
                endTime = null;
            }

            IQueryable<MemberExportInput> query = null;

            if (input.list != null && input.list.Count > 0)
            {
                 query = from m in _memberRepository.GetAll()
                            join memberInfo in _memberInfoRepository.GetAll()
                            on m.Id equals memberInfo.MemberID
                            where input.list.Contains(m.Id)
                            select new MemberExportInput
                            {
                                LoginName = m.LoginName,
                                Email = m.Email,
                                IsActive = m.IsActive,
                                RegisterForm = m.RegisterForm,
                                IsReceive = m.IsReceive,
                                IP = m.IP,
                                FirstName = memberInfo.FirstName,
                                LastName = memberInfo.LastName,
                                Phone = memberInfo.Phone,
                                Sex = memberInfo.Sex,
                                Company = memberInfo.Company,
                                Tel = memberInfo.Tel,
                                ZipCode = memberInfo.ZipCode,
                                JobTitle = memberInfo.JobTitle,
                                Address = memberInfo.Address,
                                Address1 = memberInfo.Address1,
                                Country = memberInfo.Country,
                                Province = memberInfo.Province,
                                City = memberInfo.City,
                                WebPage = memberInfo.WebPage,
                                Remark = memberInfo.Remark,
                                registerDate = memberInfo.CreationTime
                            };
            }
            else
            {
                query = from m in _memberRepository.GetAll()
                        .WhereIf(!string.IsNullOrWhiteSpace(input.Filter), item => item.LoginName.Contains(input.Filter))
                                         .WhereIf(input.IsReceive == true, item => item.IsReceive == true)
                                         .WhereIf(input.IsReceive == false, item => item.IsReceive == false)
                                         .WhereIf(input.Enabled == true, item => item.IsActive == true)
                                         .WhereIf(input.Enabled == false, item => item.IsActive == false)
                                         .WhereIf(input.StartTime != null && input.EndTime != null, t => t.CreationTime > startTime && t.CreationTime < endTime)
                                         .WhereIf(!string.IsNullOrWhiteSpace(input.RegisterFrom), item => item.RegisterForm.Contains(input.RegisterFrom))
                        join memberInfo in _memberInfoRepository.GetAll()
                                                                 .WhereIf(!string.IsNullOrWhiteSpace(input.Country), item => item.Country.Contains(input.Country))
                        on m.Id equals memberInfo.MemberID
                        select new MemberExportInput
                        {
                            LoginName = m.LoginName,
                            Email = m.Email,
                            IsActive = m.IsActive,
                            RegisterForm = m.RegisterForm,
                            IsReceive = m.IsReceive,
                            IP = m.IP,
                            Fax = memberInfo.Fax,
                            FirstName = memberInfo.FirstName,
                            LastName = memberInfo.LastName,
                            Phone = memberInfo.Phone,
                            Sex = memberInfo.Sex,
                            Company = memberInfo.Company,
                            Tel = memberInfo.Tel,
                            ZipCode = memberInfo.ZipCode,
                            JobTitle = memberInfo.JobTitle,
                            Address = memberInfo.Address,
                            Address1 = memberInfo.Address1,
                            Country = memberInfo.Country,
                            Province = memberInfo.Province,
                            City = memberInfo.City,
                            WebPage = memberInfo.WebPage,
                            Remark = memberInfo.Remark,
                            registerDate = memberInfo.CreationTime
                        };

            }
            query = query.OrderByDescending(item => item.registerDate);
            var list = await query.ToListAsync();

            return _exportMemberHelper.MemberExportDataList(list);
        }
    }
}
